﻿using System;
using System.Collections.ObjectModel;
using System.Net;
using System.ServiceModel.DomainServices.Client;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using XamlingCore.Infrastructure.Extensions;
using XamlingCore.Infrastructure.Repository;
using XamlingCore.Infrastructure.SystemMessage;

namespace XamlingCore.SL.RIAServices.Repository
{
    public class DomainContextRepositoryBase<TDomainContextType> : RepositoryBase where TDomainContextType : DomainContext
    {
        private TDomainContextType context;

        public DomainContextRepositoryBase(TDomainContextType context)
        {
            this.context = context;
        }

        public TDomainContextType DomainContext
        {
            get
            {
                return context;
            }
            set
            {
                context = value;
            }
        }

        public virtual void LoadOperationCompleted(LoadOperation operation)
        {

        }

        public virtual void LoadFromQuery<T>(EntityQuery<T> query, Action<ObservableCollection<T>> callback)
            where T : Entity
        {
            context.Load(query, p =>
            {
                LoadOperationCompleted(p);
                SystemMessagePackage message = Parse(p);
                if (MessageCallback != null)
                {
                    MessageCallback(message);
                }

                callback(p.Entities.AsObservableCollection());
            }, null);
        }

        public virtual void LoadFromQueryReload<T>(EntityQuery<T> query, Action<ObservableCollection<T>> callback)
            where T : Entity
        {
            context.Load(query, LoadBehavior.RefreshCurrent, p =>
            {
                LoadOperationCompleted(p);
                SystemMessagePackage message = Parse(p);
                if (MessageCallback != null)
                {
                    MessageCallback(message);
                }

                callback(p.Entities.AsObservableCollection());
            }, null);
        }

        public virtual void SubmitChanges(Action<SubmitOperation> callback)
        {
            context.SubmitChanges(p =>
            {
                SystemMessagePackage message = Parse(p);
                if (MessageCallback != null)
                {
                    MessageCallback(message);
                }

                callback(p);
            }, null);
        }


        static SystemMessagePackage Parse(LoadOperation operation)
        {
            if (operation.HasError)
            {
                return new SystemMessagePackage() { Data = operation, Message = operation.Error.Message + " (" + operationTypes(operation) + ")", IsError = true, Title = "Load Operation Problem" };
            }
            else
            {
                return new SystemMessagePackage() { Message = operationTypes(operation), Title = "Load Success", Data = operation };
            }
        }


        static SystemMessagePackage Parse(SubmitOperation operation)
        {
            if (operation.HasError)
            {
                return new SystemMessagePackage() { Data = operation, Message = operation.Error.Message + " (" + operationTypes(operation) + ")", IsError = true, Title = "Submit Operation Problem" };
            }
            else
            {
                return new SystemMessagePackage() { Message = operationTypes(operation), Title = "Submit Operation Success", Data = operation };
            }
        }

        static string operationTypes(LoadOperation operation)
        {
            string result = string.Format("Loaded {0} entities", operation.TotalEntityCount);

            if (operation.IsComplete)
            {
                result += " - Completed";
            }
            else
            {
                result += " - Not completed";
            }

            if (operation.IsCanceled)
            {
                result += " (cancelled)";
            }

            return result;
        }

        static string operationTypes(SubmitOperation operation)
        {
            bool added = operation.ChangeSet.AddedEntities.Count > 0;
            bool modified = operation.ChangeSet.ModifiedEntities.Count > 0;
            bool removed = operation.ChangeSet.RemovedEntities.Count > 0;

            string result = "";

            if (added)
            {
                result = "Added";
            }
            if (modified)
            {
                result += ", Modified";
            }
            if (removed)
            {
                result += ", Removed";
            }

            result = result.Trim(',', ' ');

            if (operation.IsComplete)
            {
                result += " - Completed";
            }
            else
            {
                result += " - Not completed";
            }

            if (operation.IsCanceled)
            {
                result += " (cancelled)";
            }

            return result;
        }
    }
}